Run.js ➔ ... ➔ this.getScenario   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
nop 0
1
var Status = require('../Schema').OperationStatus
2
var Initialization = require('./Stage/InitializationStage').InitializationStage
3
var ScenarioStage = require('./Stage/ScenarioStage').ScenarioStage
4
var Termination = require('./Stage/TerminationStage').TerminationStage
5
var Context = require('./Context').Context
6
var Executor = require('./Executor').Executor
7
var SDK = require('@ama-team/voxengine-sdk')
8
var Slf4j = SDK.Logger.Slf4j
9
var Future = SDK.Concurrent.Future
10
11
/**
12
 * Scenario consists of three states: initialization (setup), execution and
13
 * termination (tear down). This class simply wraps them in a single unit of
14
 * execution, allowing to run whole scenario (nearly) at once.
15
 *
16
 * @param {TScenario} scenario
17
 * @param {TArgumentHandler} deserializer
18
 * @param {TRunOptions} [options]
19
 *
20
 * @class
21
 */
22
function Run (scenario, deserializer, options) {
23
  options = options || {}
24
  var logger = Slf4j.factory(options.logger, 'ama-team.vsf.execution.run')
25
  var context = new Context(this, options)
26
  var executor = new Executor(context)
27
  var initialization = new Initialization(executor, deserializer)
28
  var execution = new ScenarioStage(executor, scenario, options)
29
  var termination = new Termination(executor, scenario.onTermination, options)
30
  var stageResults = {
31
    initialization: null,
32
    scenario: null,
33
    termination: null
34
  }
35
  var result = {
36
    stages: stageResults,
37
    startedAt: null,
38
    finishedAt: null,
39
    status: null,
40
    error: null
41
  }
42
  var completion = new Future()
43
44
  /**
45
   * Starts run. Run performs some initialization and then stops until scenario
46
   * trigger is passed to #run() method
47
   *
48
   * @return {Thenable.<TRunResult>}
49
   */
50
  this.initialize = function () {
51
    result.startedAt = new Date()
52
    logger.info('Running initialization stage')
53
    initialization
54
      .initialize()
55
      .then(function (value) {
56
        if (value.status.successful) {
57
          logger.info('Finished initialization stage')
58
        } else {
59
          logger.error('Initialization stage has failed:', value.error)
60
        }
61
        stageResults.initialization = value
62
        logger.info('Running execution stage')
63
        if (value.status.successful) {
64
          return execution.run()
65
        } else {
66
          var message = 'Execution (scenario) stage is not run due to ' +
67
            'initialization stage fail'
68
          logger.warn(message)
69
          return null
70
        }
71
      })
72
      .then(function (value) {
73
        stageResults.scenario = value
74
        if (!value || value.status.successful) {
75
          logger.info('Finished execution stage')
76
        } else {
77
          logger.error('Execution stage has failed:', value.value)
78
        }
79
        logger.info('Running termination stage')
80
        return termination.run(stageResults.initialization, value)
81
      })
82
      .then(function (value) {
83
        stageResults.termination = value
84
        if (value.status.successful) {
85
          logger.info('Finished termination stage')
86
        } else {
87
          logger.error('Termination stage has failed:', value.value)
88
        }
89
      })
90
      .then(function () {
91
        logger.info('Finished run')
92
        var weights = [Status.Finished, Status.Failed, Status.Tripped]
93
        result.status = Object.keys(stageResults).reduce(function (carrier, key) {
94
          var item = stageResults[key] && stageResults[key].status
95
          var weight = weights.indexOf(item)
96
          return weight > weights.indexOf(carrier) ? item : carrier
97
        }, Status.Finished)
98
      }, function (reason) {
99
        logger.info('Run has finished with unexpected error: {}', reason)
100
        result.status = Status.Tripped
101
        result.error = reason
102
      })
103
      .then(function () {
104
        result.finishedAt = new Date()
105
        result.duration = result.finishedAt.getTime() - result.startedAt.getTime()
106
        completion.resolve(result)
107
      })
108
    return completion
109
  }
110
111
  /**
112
   * @param {string} url
113
   */
114
  this.setLog = function (url) {
115
    initialization.setLog(url)
116
  }
117
118
  /**
119
   * @param {TScenarioTrigger} value
120
   *
121
   * @return {Thenable.<TRunResult>}
122
   */
123
  this.proceed = function (value) {
124
    initialization.proceed(value)
125
    return completion
126
  }
127
128
  /**
129
   * @param {TScenarioTrigger} trigger
130
   * @param {string} [log]
131
   *
132
   * @return {Thenable.<TRunResult>}
133
   */
134
  this.execute = function (trigger, log) {
135
    this.initialize()
136
    this.setLog(log)
137
    return this.proceed(trigger)
138
  }
139
140
  /**
141
   * @return {TScenario}
142
   */
143
  this.getScenario = function () {
144
    return scenario
145
  }
146
147
  this.transitionTo = function (id, hints) {
148
    return execution.getStateMachine().transitionTo(id, hints)
149
  }
150
151
  this.getCompletion = function () {
152
    return completion
153
  }
154
155
  this.getExecutor = function () {
156
    return executor
157
  }
158
}
159
160
module.exports = {
161
  Run: Run
162
}
163